﻿' LibWowArmory
' by Ronald M. Clifford (roncli@roncli.com)
'
' This source code is released under the GNU Library General Public License (LGPL) Version 2.1.

Imports Newtonsoft.Json
Imports System
Imports System.Collections.Generic
Imports System.Text.RegularExpressions

Namespace roncliProductions.LibWowArmory

    ''' <summary>
    ''' A class that defines the events for a given month on a player's calendar
    ''' </summary>
    ''' <remarks></remarks>
    Public Class CalendarMonthWorld
        Inherits WowArmoryData

        Private cmwCalendar As New CalendarMonthWorldSchema.calendarMonthWorld
        Private eEvents As New List(Of [Event])
        Private strRealm As String
        Private strName As String
        Private dtMonth As Date
        Private ctType As CalendarType

        ''' <summary>
        ''' The realm of the character for the calendar to lookup
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Realm() As String
            Get
                Return strRealm
            End Get
            Set(ByVal value As String)
                strRealm = value
            End Set
        End Property

        ''' <summary>
        ''' The name of the character for the calendar to lookup
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Name() As String
            Get
                Return strName
            End Get
            Set(ByVal value As String)
                strName = value
            End Set
        End Property

        ''' <summary>
        ''' The month of the character's calendar to lookup.  Note that only month and year are stored.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Month() As Date
            Get
                Return dtMonth
            End Get
            Set(ByVal value As Date)
                dtMonth = New Date(value.Year, value.Month, 1)
            End Set
        End Property

        ''' <summary>
        ''' The type of calendar events to retrieve.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Type() As CalendarType
            Get
                Return ctType
            End Get
            Set(ByVal value As CalendarType)
                ctType = value
            End Set
        End Property

        ''' <summary>
        ''' The URL that will be used to retrieve the character's calendar from the armory
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property URL() As String
            Get
                Dim strType As String = ""
                Select Case ctType
                    Case Enums.CalendarType.BattlegroundHolidays
                        strType = "bg"
                    Case Enums.CalendarType.DarkmoonFaire
                        strType = "darkmoon"
                    Case Enums.CalendarType.RaidLockouts
                        strType = "raidLockout"
                    Case Enums.CalendarType.RaidResets
                        strType = "raidReset"
                    Case Enums.CalendarType.WeeklyHolidays
                        strType = "holidayWeekly"
                    Case Enums.CalendarType.WorldHolidays
                        strType = "holiday"
                End Select
                Return String.Format("http://www.wowarmory.com/vault/calendar/month-world.json?callback=calendar.loadEvents&r={0}&n={1}&year={2}&month={3}&loc=en_us&type={4}", strRealm, strName, dtMonth.Year, dtMonth.Month, strType)
            End Get
        End Property

        ''' <summary>
        ''' Indicates to the inherited class that this request requires login
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overrides ReadOnly Property RequiresLogin() As Boolean
            Get
                Return True
            End Get
        End Property

        ''' <summary>
        ''' The month's calendar type
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property CalendarType() As String
            Get
                Return cmwCalendar.calendarType
            End Get
        End Property

        ''' <summary>
        ''' The timezone offset of the event's server
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property TimezoneOffset() As TimeSpan
            Get
                Return New TimeSpan(0, 0, 0, 0, CInt(cmwCalendar.tz))
            End Get
        End Property

        ''' <summary>
        ''' The list of events for the month
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Property Events() As List(Of [Event])
            Get
                Return eEvents
            End Get
            Set(ByVal value As List(Of [Event]))
                eEvents = value
            End Set
        End Property

        ''' <summary>
        ''' A constructor to create a new calendar month for a character
        ''' </summary>
        ''' <param name="strUsername">The World of Warcraft/battle.net account username</param>
        ''' <param name="strPassword">The World of Warcraft/battle.net account password</param>
        ''' <param name="strRealm">The realm of the character for the calendar to lookup</param>
        ''' <param name="strName">The name of the character for the calendar to lookup</param>
        ''' <param name="dtMonth">The month of the character's calendar to lookup.  Note that only month and year are stored.</param>
        ''' <param name="ctType">The type of calendar events to return</param>
        ''' <remarks></remarks>
        Public Sub New(ByVal strUsername As String, ByVal strPassword As String, ByVal strRealm As String, ByVal strName As String, ByVal dtMonth As Date, ByVal ctType As CalendarType)
            Me.Username = strUsername
            Me.Password = strPassword
            Me.strRealm = strRealm
            Me.strName = strName
            Me.Month = dtMonth
            Me.ctType = ctType
            Load()
        End Sub

        ''' <summary>
        ''' Loads and deserialzes the JSON data
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub Load()
            MyBase.Retrieve()

            strData = Regex.Match(strData, "calendar.loadEvents\((.*)\);").Groups(1).Value

            cmwCalendar = CType(JavaScriptConvert.DeserializeObject(strData, GetType(CalendarMonthWorldSchema.calendarMonthWorld)), CalendarMonthWorldSchema.calendarMonthWorld)

            eEvents.Clear()

            If cmwCalendar Is Nothing Then
                Throw New InvalidOperationException("The calendar did not return any information.")
                Exit Sub
            End If

            If cmwCalendar.events Is Nothing Then
                Exit Sub
            End If

            For Each eEvent As CalendarMonthWorldSchema.event In cmwCalendar.events
                eEvents.Add(New [Event](eEvent.calendarType, eEvent.calendarTypeId, eEvent.description, eEvent.end, eEvent.icon, eEvent.priority, eEvent.start, eEvent.summary, Me))
            Next
        End Sub

        ''' <summary>
        ''' A class that defines an event
        ''' </summary>
        ''' <remarks></remarks>
        Public Class [Event]
            Private strCalendarType As String
            Private intCalendarTypeID As Integer
            Private strDescription As String
            Private lngEnd As Long
            Private strIcon As String
            Private intPriority As Integer
            Private lngStart As Long
            Private strSummary As String
            Private cmwParent As CalendarMonthWorld

            ''' <summary>
            ''' The calendar type of the calendar event
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public ReadOnly Property CalendarType() As String
                Get
                    Return strCalendarType
                End Get
            End Property

            ''' <summary>
            ''' The identification number of the calendar type of the calendar event
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public ReadOnly Property CalendarTypeID() As Integer
                Get
                    Return intCalendarTypeID
                End Get
            End Property

            ''' <summary>
            ''' A description of the event
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public ReadOnly Property Description() As String
                Get
                    Return strDescription
                End Get
            End Property

            ''' <summary>
            ''' The end date of the event, in UTC
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public ReadOnly Property UTCEnd() As Date
                Get
                    Return New Date(1970, 1, 1).AddMilliseconds(lngEnd)
                End Get
            End Property

            ''' <summary>
            ''' The icon of the calendar event
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public ReadOnly Property Icon() As String
                Get
                    Return strIcon
                End Get
            End Property

            ''' <summary>
            ''' The priority of the event
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public ReadOnly Property Priority() As Integer
                Get
                    Return intPriority
                End Get
            End Property

            ''' <summary>
            ''' The start date of the event, in UTC
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public ReadOnly Property UTCStart() As Date
                Get
                    Return New Date(1970, 1, 1).AddMilliseconds(lngStart)
                End Get
            End Property

            ''' <summary>
            ''' The summary of the calendar event
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public ReadOnly Property Summary() As String
                Get
                    Return strSummary
                End Get
            End Property

            ''' <summary>
            ''' The start date of the event, in server time
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public ReadOnly Property [End]() As Date
                Get
                    If strCalendarType = "holidayWeekly" Then
                        Return New Date(1970, 1, 1).AddMilliseconds(lngEnd).Add(cmwParent.TimezoneOffset).AddHours(12)
                    Else
                        Return New Date(1970, 1, 1).AddMilliseconds(lngEnd).Add(cmwParent.TimezoneOffset)
                    End If
                End Get
            End Property

            ''' <summary>
            ''' The start date of the event, in server time
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public ReadOnly Property Start() As Date
                Get
                    If strCalendarType = "holidayWeekly" Then
                        Return New Date(1970, 1, 1).AddMilliseconds(lngStart).Add(cmwParent.TimezoneOffset).AddHours(12)
                    Else
                        Return New Date(1970, 1, 1).AddMilliseconds(lngStart).Add(cmwParent.TimezoneOffset)
                    End If
                End Get
            End Property

            ''' <summary>
            ''' A constructor to create a new calendar event
            ''' </summary>
            ''' <param name="strCalendarType"></param>
            ''' <param name="intCalendarTypeID"></param>
            ''' <param name="strDescription"></param>
            ''' <param name="lngEnd"></param>
            ''' <param name="strIcon"></param>
            ''' <param name="intPriority"></param>
            ''' <param name="lngStart"></param>
            ''' <param name="strSummary"></param>
            ''' <param name="cmwParent"></param>
            ''' <remarks></remarks>
            Public Sub New(ByVal strCalendarType As String, ByVal intCalendarTypeID As Integer, ByVal strDescription As String, ByVal lngEnd As Long, ByVal strIcon As String, ByVal intPriority As Integer, ByVal lngStart As Long, ByVal strSummary As String, ByRef cmwParent As CalendarMonthWorld)
                Me.strCalendarType = strCalendarType
                Me.intCalendarTypeID = intCalendarTypeID
                Me.strDescription = strDescription
                Me.lngEnd = lngEnd
                Me.strIcon = strIcon
                Me.intPriority = intPriority
                Me.lngStart = lngStart
                Me.strSummary = strSummary
                Me.cmwParent = cmwParent
            End Sub

        End Class

    End Class

End Namespace